package de.hft_stuttgart.botwar.database;

import de.hft_stuttgart.botwar.server.model.RobotConfiguration;
import java.io.Serializable;
import java.util.Calendar;
import java.util.Collection;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
import javax.persistence.Transient;

/**
 *
 * @author pmv-mail@gmx.de
 */
@Entity
@Table(name="tblPlayer")
public class Player implements Serializable {
    @Id
    @Column(name="Username")
    private String username;

    @Column(name="\"E-Mail\"", nullable=false)
    private String email;

    @Column(name="Password", nullable=false)
    private String pwd;

    @OneToMany(cascade=CascadeType.REMOVE)
    private Collection<RobotConfiguration> robots;

    @OneToOne(cascade=CascadeType.ALL, optional=false)
    @PrimaryKeyJoinColumn()
    private Statistic stat;

    @Transient
    private long onlineTimer = 0;
    @Transient
    private long playingTimer = 0;

    /**
     * This constructor just exists because of the requirements of jpa.
     * Please do not use.
     * @deprecated
     */
    @Deprecated
    public Player(){
    }

    /**
     *
     * @param username name from player
     * @param email e-mail from player
     * @param pwd password from player
     */
    public Player(final String username, final String email, final String pwd){
        this.username = username;
        this.email = email;
        this.pwd = pwd;
        this.stat = new Statistic(this);
    }

    /**
     *
     * @param username name from player
     * @param email from player
     * @param pwd pwd from player
     * @param stat statistic-object from player
     */
    public Player(final String username,
                  final String email,
                  final String pwd,
                  final Statistic stat){
        this.username = username;
        this.email = email;
        this.pwd = pwd;
        this.stat = stat;
    }
    /**
     *
     * @return name of this player
     */
    public String getUsername() {
        return username;
    }

    /**
     *
     * @return e-mail of this player
     */
    public String getEmail() {
        return email;
    }

    /**
     *
     * @param email e-mail of this player
     */
    public void setEmail(final String email) {
        this.email = email;
    }

    /**
     *
     * @return password of this player
     */
    public String getPwd() {
        return pwd;
    }

    /**
     *
     * @param pwd password of this player
     */
    public void setPwd(final String pwd) {
        this.pwd = pwd;
    }

    /**
     *
     * @return list of robots from this player
     */
    public Collection<RobotConfiguration> getRobots(){
        return robots;
    }

    /**
     *
     * @return statistic from this player
     */
    public Statistic getStat() {
        return stat;
    }

    /**
     * Saves the current time as the login-time for future calculation.
     */
    public void login(){
        if (onlineTimer != 0){
            throw new IllegalStateException("Player is already logged in!");
        }
        this.onlineTimer = Calendar.getInstance().getTimeInMillis();
    }

    /**
     * Called from the database to update the online time statistic.
     * @param stat the current statistic object from the db
     */
    public void logout(final Statistic stat) {
        if (onlineTimer == 0){
            throw new IllegalStateException("Player has not logged in!");
        }
        Calendar now = Calendar.getInstance();
        this.stat = stat;
        if (isPlaying()){
            finishPlaying(stat);
        }
        this.getStat().addOnlineTime(now.getTimeInMillis() - onlineTimer);
        this.getStat().setLastOnlineTime(now);

    }
    /**
     * Returns the current playing state of this player.
     * @return true if the player is in a running game, otherwise false
     */
    public boolean isPlaying(){
        return playingTimer != 0;
    }

    /**
     * Saves the current time as the beginning of a game for future use.
     */
    public void startPlaying() {
        if (isPlaying()){
            throw new IllegalStateException(
                                    "Player is already in a running game!");
        }
        this.playingTimer = Calendar.getInstance().getTimeInMillis();
    }

    /**
     * Called from the DataBase to update the time statistic after a game
     * @param stat the current statistic object from the db
     */
    public void finishPlaying(final Statistic stat) {
        if (!isPlaying()){
            throw new IllegalStateException("Player has not started a game!");
        }
        Calendar now = Calendar.getInstance();
        this.stat = stat;
        this.getStat().addPlayingTime(now.getTimeInMillis() - playingTimer);
        playingTimer = 0;
    }

    /**
     * @return returns the time in milliseconds, the player is currently
     * logged in.
     */
    public long getSessionTime(){
        if (onlineTimer != 0){
            return System.currentTimeMillis() - onlineTimer;
        }
        return 0;
    }

}
